package sys

/*******************************************************************************
Copyright:cloud
Author:cloudapex@126.com
Version:1.0
Date:2020-06-12
Description: 用户相关接口
*******************************************************************************/
import (
	"context"
	model "service/model/hr"
	mCache "service/model/hr_cache"
	"service/model/mod"
	mPerm "service/model/permis"

	gpc "gitee.com/cloudapex/protos/comm/pb"
	gpb "gitee.com/cloudapex/protos/hr/pb"
	gpa "gitee.com/cloudapex/protos/hr_cache/pb"
	gpp "gitee.com/cloudapex/protos/permis/pb"

	"gitee.com/cloudapex/ulern/htp"
	"gitee.com/cloudapex/ulern/util"
	"github.com/gin-gonic/gin"
)

/*
 * 描述: 用户列表
 * 路由: /user/list
 * 方法: GET
 *********************************************************************/
type UserList struct {
	mod.SortFinder
	mod.PageFinder

	Acct      string `form:"acct" json:"acct" binding:"omitempty,max=64"`    // 账号
	Name      string `form:"name" json:"name" binding:"omitempty,max=64"`    // 用户名
	CreateBgn int64  `form:"createBgn" json:"createBgn" binding:"omitempty"` // 创建时间(int)
	CreateEnd int64  `form:"createEnd" json:"createEnd" binding:"omitempty"` // 创建时间(int)
	LastBgn   int64  `form:"lastBgn" json:"lastBgn" binding:"omitempty"`     // 上次登录时间(int)
	LastEnd   int64  `form:"lastEnd" json:"lastEnd" binding:"omitempty"`     // 上次登录时间(int)
}
type userListRsp struct {
	Id         int64  `json:"id"`         //账户ID(用户Id)
	Name       string `json:"name"`       //姓名(用户名)
	CommpId    int64  `json:"commpId"`    //公司ID
	Phone      string `json:"phone"`      //手机号(登录账号)
	HId        int64  `json:"hId"`        //员工ID
	WorkName   string `json:"workName"`   //工号姓名
	CreateAt   int64  `json:"createAt"`   //创建时间
	CreateId   int64  `json:"createId"`   //创建人ID(员工Id)
	CreateName string `json:"createName"` //创建人
	RoleId     int64  `json:"roleId"`     //角色ID(种类)
	Status     int64  `json:"status"`     //状态 1 启用 2 禁用
	UpdateAt   int64  `json:"updateAt"`   //更新时间
	LoginAt    int64  `json:"loginAt"`    //最后登录时间
}

func (this *UserList) Handle(c *gin.Context, ctx context.Context) htp.Response {
	user := mod.CurrUser(c)

	rsp, err := model.CrmUser.UserList(ctx, &gpb.UserInfoListReq{
		CommpId: user.CId,
		Page:    int64(this.PageFinder.Page),
		Count:   int64(this.PageFinder.Pnum),
		Order:   int64(this.SortFinder.Order),
		Orule:   int64(this.SortFinder.Orule) + 1,

		Phone:  this.Acct,
		Name:   this.Name,
		CsTime: this.CreateBgn,
		CeTime: this.CreateEnd,
		LsTime: this.LastBgn,
		LeTime: this.LastEnd,
	})
	if err != nil {
		return htp.RespModelErr("_u", err)
	}

	items := []*userListRsp{}
	if err := util.Convert(&items, rsp.Data); err != nil {
		return htp.RespConvertErr("", err)
	}

	// 取得员工姓名
	if resp := this.HandleWorkNames(c, ctx, items); resp.Err() != nil {
		return resp
	}

	// 取得创建人姓名
	if resp := this.HandleCreateNames(c, ctx, items); resp.Err() != nil {
		return resp
	}

	return htp.RespOK("", &struct {
		Total int64       `json:"total"`
		List  interface{} `json:"list"`
	}{rsp.Total, items})
}
func (this *UserList) HandleWorkNames(c *gin.Context, ctx context.Context, items []*userListRsp) htp.Response {
	if len(items) == 0 {
		return htp.RespOK("", nil)
	}

	user := mod.CurrUser(c)

	hIds := []int64{}
	for _, it := range items {
		hIds = append(hIds, it.HId)
	}

	rspNameList, err := mCache.StaffCacheServer.GetStaffNameList(ctx, &gpa.StaffNameReqIdsReq{CId: user.CId, Ids: hIds})
	if err != nil {
		return htp.RespModelErr("_w", err)
	}
	for _, it := range items {
		for _, na := range rspNameList.NameList {
			if it.HId == na.Id {
				it.WorkName = na.Name
				break
			}
		}
	}
	return htp.RespOK("", nil)
}
func (this *UserList) HandleCreateNames(c *gin.Context, ctx context.Context, items []*userListRsp) htp.Response {
	if len(items) == 0 {
		return htp.RespOK("", nil)
	}

	user := mod.CurrUser(c)

	uIds := []int64{}
	for _, it := range items {
		uIds = append(uIds, it.CreateId)
	}
	rspNameList, err := mCache.UserCacheServer.UserNameList(ctx, &gpa.UserLoginReqIdsReq{CId: user.CId, Ids: uIds})
	if err != nil {
		return htp.RespModelErr("_c", err)
	}
	for _, it := range items {
		for _, na := range rspNameList.NameList {
			if it.CreateId == na.Id {
				it.CreateName = na.Name
				break
			}
		}
	}
	return htp.RespOK("", nil)
}

/*
 * 描述: 新增用户
 * 路由: /user/add
 * 方法: POST
 *********************************************************************/
type UserAdd struct {
	Acct string  `form:"acct" json:"acct" binding:"required,max=64"` // 账号(手机号)
	Name string  `form:"name" json:"name" binding:"required,max=64"` // 用户名
	HId  int64   `form:"hId" json:"hId" binding:"omitempty"`         // 员工ID
	Kind int32   `form:"kind" json:"kind" binding:"required"`        // 角色种类
	RIds []int64 `form:"rIds" json:"rIds" binding:"omitempty"`       // 角色Ids
}

func (this *UserAdd) Handle(c *gin.Context, ctx context.Context) htp.Response {
	user := mod.CurrUser(c)
	phone := this.Acct
	cId := user.CId

	isUpdate, err := checkOutPhone(ctx, cId, phone, 0)

	if err != nil {
		return htp.RespDBErr("", err)
	}
	if isUpdate {
		return htp.RespDBErr("此用户手机号已存在，请重新填写手机号！", err)
	}
	rsp, err := model.CrmUser.UserAdd(ctx, &gpb.UserReq{
		CommpId:  user.CId,
		Phone:    this.Acct,
		Name:     this.Name,
		Pass:     util.MD5([]byte(this.Acct)),
		HId:      this.HId,
		CreateId: user.UId,
		RoleId:   int64(this.Kind),
		Status:   1,
	})

	if err != nil {
		return htp.RespModelErr("", err)
	}
	// _, err = mPerm.Sysm.UserAdd(ctx, &gpp.UserAddReq{CoId: user.CId, Id: rsp.Id, Name: this.Name, State: 1})
	// if err != nil {
	// 	return htp.RespModelErr("", err)
	// }
	_, err = mPerm.Sysm.UserChoose(ctx, &gpp.UserChooseReq{Id: rsp.Id, RIds: this.RIds})
	if err != nil {
		return htp.RespModelErr("", err)
	}
	_, err = mCache.UserCacheServer.AddLoginCacheInfo(ctx, &gpa.LoginCacheReq{
		Id:       rsp.Id,
		CId:      user.CId,
		HId:      this.HId,
		Name:     this.Name,
		Phone:    this.Acct,
		At:       rsp.CreateAt,
		UpdateAt: rsp.UpdateAt,
		RoleId:   int64(this.Kind),
	})
	if err != nil {
		return htp.RespModelErr("", err)
	}
	return htp.RespOK("", &struct {
		Id int64 `json:"id"` // 用户Id
	}{rsp.Id})
}

/*
 * 描述: 编辑用户
 * 路由: /user/upd
 * 方法: POST
 *********************************************************************/
type UserUpd struct {
	Id   int64   `form:"id" json:"id" binding:"required"`            // 用户Id
	Acct string  `form:"acct" json:"acct" binding:"required,max=64"` // 账号
	Name string  `form:"name" json:"name" binding:"required,max=64"` // 用户名
	HId  int64   `form:"hId" json:"hId" binding:"omitempty"`         // 员工ID
	Kind int32   `form:"kind" json:"kind" binding:"required"`        // 角色种类
	RIds []int64 `form:"rIds" json:"rIds" binding:"omitempty"`       // 角色Ids
}

func (this *UserUpd) Handle(c *gin.Context, ctx context.Context) htp.Response {
	user := mod.CurrUser(c)

	phone := this.Acct
	id := this.Id
	cId := user.CId

	isUpdate, err := checkOutPhone(ctx, cId, phone, id)

	if err != nil {
		return htp.RespDBErr("", err)
	}
	if isUpdate {
		return htp.RespDBErr("此用户手机号已存在，请重新填写手机号！", err)
	}

	_, err = model.CrmUser.UserUpd(ctx, &gpb.UserReq{
		Id:     this.Id,
		Phone:  this.Acct,
		Name:   this.Name,
		HId:    this.HId,
		RoleId: int64(this.Kind),
	})
	if err != nil {
		return htp.RespModelErr("", err)
	}

	// _, err = mPerm.Sysm.UserUpd(ctx, &gpp.UserUpdReq{Id: this.Id, Name: this.Name, State: 1})
	// if err != nil {
	// 	return htp.RespModelErr("", err)
	// }

	_, err = mPerm.Sysm.UserChoose(ctx, &gpp.UserChooseReq{Id: this.Id, RIds: this.RIds})
	if err != nil {
		return htp.RespModelErr("", err)
	}

	autoAssignReq := &gpa.LoginCacheReq{
		Id: this.Id,
	}
	autoAssignInfo, err := mCache.UserCacheServer.GetAllLoginCache(ctx, autoAssignReq)
	userInfo := autoAssignInfo.UserInfo

	_, err = mCache.UserCacheServer.EditLoginCacheInfo(ctx, &gpa.LoginCacheReq{
		Id:       userInfo.Id,
		CId:      userInfo.CId,
		Name:     this.Name,
		RoleId:   int64(this.Kind),
		HId:      userInfo.HId,
		Phone:    this.Acct,
		At:       userInfo.At,
		UpdateAt: userInfo.UpdateAt,
	})
	if err != nil {
		return htp.RespModelErr("", err)
	}
	return htp.RespOK("", nil)
}

func checkOutPhone(ctx context.Context, CId int64, phone string, id int64) (isUpdate bool, err error) {
	rsp2, err := model.CrmUser.UserList(ctx, &gpb.UserInfoListReq{
		CommpId: CId,
		Phone:   phone,
	})
	if err != nil {
		return
	}
	//  是否可以更新（有重复的不进行更新）
	if len(rsp2.Data) > 0 {
		for _, v := range rsp2.Data {

			if v.Phone == phone {

				if id == 0 || (id != 0 && id != v.Id) {
					isUpdate = true
				}
			}

		}

	}
	return
}

/*
 * 描述: 更改用户状态
 * 路由: /user/sta
 * 方法: POST
 *********************************************************************/
type UserSta struct {
	Id    int64 `form:"id" json:"id" binding:"required"`       // 用户Id
	State int32 `form:"state" json:"state" binding:"required"` // 状态(1:正常;2:失效)
}

func (this *UserSta) Handle(c *gin.Context, ctx context.Context) htp.Response {
	//user := comm.CurrUser(c)

	_, err := model.CrmUser.UserSta(ctx, &gpb.UserInfoStatusReq{
		Ids:    []int64{this.Id},
		Status: int64(this.State),
	})
	if err != nil {
		return htp.RespModelErr("", err)
	}

	// _, err = mPerm.Sysm.UserSta(ctx, &gpp.UserStaReq{Id: this.Id, State: this.State})
	// if err != nil {
	// 	return htp.RespModelErr("", err)
	// }
	return htp.RespOK("", nil)
}

/*
 * 描述: 重置密码
 * 路由: /user/pwd
 * 方法: POST
 *********************************************************************/

type UserPwd struct {
	Id   int64  `form:"id" json:"id" binding:"required"`            // 用户Id
	Acct string `form:"acct" json:"acct" binding:"required,max=64"` // 账号
}

func (this *UserPwd) Handle(c *gin.Context, ctx context.Context) htp.Response {
	//user := comm.CurrUser(c)

	_, err := model.CrmUser.UserPwd(ctx, &gpb.UserReq{
		Id:   this.Id,
		Pass: util.MD5([]byte(this.Acct)),
	})
	if err != nil {
		return htp.RespModelErr("", err)
	}
	return htp.RespOK("", nil)
}

/*
 * 描述: 删除用户 (不允许删除)
 * 路由: /user/del
 * 方法: POST
 *********************************************************************/

// type UserDel struct {
// 	Id int64 `form:"id" json:"id" binding:"required"` // 用户Id
// }

// func (this *UserDel) Handle(c *gin.Context, ctx context.Context) htp.Response {
// 	//user := comm.CurrUser(c)

// 	rsp, err := model.Sysm.UserDel(ctx, &gpc.IdRequest{Id: this.Id})
// 	if err != nil {
// 		return htp.RespModelErr("", err)
// 	}
// 	return htp.RespOK("", rsp)
// }

/*
 * 描述: 获取用户的组织角色
 * 路由: /user/choice
 * 方法: GET
 *********************************************************************/
type UserChoice struct {
	Id int64 `form:"id" json:"id" binding:"required"` // 用户Id
}

func (this *UserChoice) Handle(c *gin.Context, ctx context.Context) htp.Response {
	//user := comm.CurrUser(c)

	rsp, err := mPerm.Sysm.UserChoice(ctx, &gpc.IdRequest{Id: this.Id})
	if err != nil {
		return htp.RespModelErr("", err)
	}
	return htp.RespOK("", rsp)
}

/*
 * 描述: 修改用户的组织角色
 * 路由: /user/choose
 * 方法: POST
 *********************************************************************/
type UserChoose struct {
	Id   int64   `form:"uid" json:"uid" binding:"required"`    // 用户Id
	RIds []int64 `form:"rids" json:"rids" binding:"omitempty"` // 角色Ids
	GIds []int64 `form:"gids" json:"gids" binding:"omitempty"` // 用户组Ids
}

func (this *UserChoose) Handle(c *gin.Context, ctx context.Context) htp.Response {
	//user := model.CurrUser(c)

	this.RIds = util.RemoveDuplicate64(this.RIds)
	this.GIds = util.RemoveDuplicate64(this.GIds)
	rsp, err := mPerm.Sysm.UserChoose(ctx, &gpp.UserChooseReq{Id: this.Id, RIds: this.RIds, GIds: this.GIds})
	if err != nil {
		return htp.RespModelErr("", err)
	}
	return htp.RespOK("", rsp)
}

/*
 * 描述: 获取用户的权限信息
 * 路由: /user/permis
 * 方法: GET
 *********************************************************************/
type UserPermis struct {
	UId  int64  `form:"uId" json:"uId" binding:"omitempty"`          // UId
	Name string `form:"name" json:"name" binding:"omitempty,max=64"` // 名称
}

func (this *UserPermis) Handle(c *gin.Context, ctx context.Context) htp.Response {
	//user := model.CurrUser(c)

	if this.UId == 0 && this.Name == "" {
		return htp.RespParamErr("请至少使用一个查询条件", nil)
	}

	rsp, err := mPerm.Sysm.UserPermis(ctx, &gpp.UserPermisReq{UId: this.UId, Name: this.Name})
	if err != nil {
		return htp.RespModelErr("", err)
	}
	return htp.RespOK("", rsp)
}

/*
 * 描述: 用户名模糊匹配
 * 路由: /user/uNameMatch
 * 方法: GET
 *********************************************************************/
type UNameMatch struct {
	Name  string `form:"name" json:"name" binding:"omitempty,max=64"` // 用户名
	Role  int32  `form:"role" json:"role" binding:"omitempty"`        // 角色类型(0:全部, 其他:角色Id(角色种类))
	Role1 int32  `form:"role1" json:"role1" binding:"omitempty"`      // 后端拼装数组
	Role2 int32  `form:"role2" json:"role2" binding:"omitempty"`      // 后端拼装数组
}

func (this *UNameMatch) Handle(c *gin.Context, ctx context.Context) htp.Response {
	user := mod.CurrUser(c)

	type rspItem struct {
		Id   int64  `json:"id"`
		Name string `json:"name"`
		Role int32  `json:"role"` // role kind
	}

	roles := []int32{}
	util.Cast(this.Role != 0, func() { roles = append(roles, this.Role) }, nil)
	util.Cast(this.Role1 != 0, func() { roles = append(roles, this.Role1) }, nil)
	util.Cast(this.Role2 != 0, func() { roles = append(roles, this.Role2) }, nil)
	rsp, err := model.CrmUser.UserList(ctx, &gpb.UserInfoListReq{
		CommpId: user.CId,
		Page:    1,
		Count:   20,
		Name:    this.Name,
		Status:  1,
	})
	if err != nil {
		return htp.RespModelErr("", err)
	}

	util.Debug("返回的用户列表%s", rsp)

	items := []rspItem{}
	for _, it := range rsp.Data {
		if len(roles) == 0 {
			items = append(items, rspItem{it.Id, it.Name, int32(it.RoleId)})
		} else if util.Containi(int32(it.RoleId), roles...) {
			items = append(items, rspItem{it.Id, it.Name, int32(it.RoleId)})
		}
	}

	return htp.RespOK("", &struct {
		List interface{} `json:"list"`
	}{items})
}
